#include "treegen2d.h"
#include "shadow2d.h"
#include "treegen.h"
#include "common.h"
using namespace std;
#define PI 3.14
#define ITERATIONS 10


/***** Tree Gen 2D methods****/
TreeGen2D::TreeGen2D() : TreeGen(){
}


void TreeGen2D::genTree(){
    treeRoot->start = float3(200,5,0);
    treeRoot->end = float3(200,20,0);
    treeRoot->aux = NULL;
    treeRoot->term = NULL;
    treeRoot->theta = PI/2.0;
    treeRoot->diameter = 1;
    treeRoot->direction = float3(0,1,0);
    initializeBud(treeRoot);
    //stupidGen(treeRoot, 0);
}

void TreeGen2D::stupidGen(Bud *b, int depth){
    if(depth < 1){
        b->aux = new Bud();
        createBudFromBud(b, b->aux);
        //float theta = rand()*3.14/2.0 + 3.14/2.0;
        b->aux->theta =  b->theta - (rand()%100)/100.0*PI/6.0;
        b->aux->end = float3(b->end.x + 1.5*cos(b->aux->theta), b->end.y + 1.5*sin(b->aux->theta),0);
        b->aux->diameter = 1;
        initializeBud(b->aux);

        b->term = new Bud();
        createBudFromBud(b, b->term);
        b->term->theta = (rand()%100)/100.0*PI/6.0 + b->theta;
        b->term->end = float3(b->end.x + 20*cos(b->term->theta), b->end.y + 20*sin(b->term->theta),0);
        b->term->diameter = 1;
        initializeBud(b->term);


        stupidGen(b->aux, depth +1);
        stupidGen(b->term, depth +1);
    }
}

void TreeGen2D::iterateShadowB(Shadow2D *shadowGrid){
    for(int i =0; i< ITERATIONS; i++){
        shadowGrid->populateGrid(this->treeRoot, 500, 500);
        shadowGrid->queryQ(this->treeRoot);
        this->passBH();
        this->produceShoots(this->treeRoot);
        this->calculateBranchDiameter(this->treeRoot);
        this->shedBranches(treeRoot);
    }
    shadowGrid->populateGrid(this->treeRoot, 500, 500);

}


void TreeGen2D::updateTree(){}
float3 TreeGen2D::findDirection(){}
void TreeGen2D::chooseBudFate(){}
void TreeGen2D::calculateBranchDiameter(Bud *b){
    float d = 0;
    if(b->term){
        this->calculateBranchDiameter(b->term);
        d += pow(b->term->diameter,DIAMETER_RATE  );
    }
    else
        d+=2;

    if(b->aux){
        this->calculateBranchDiameter(b->aux);
        d+= pow(b->aux->diameter,DIAMETER_RATE  );
    }
    else
        d+=2;

    b->diameter = pow(d, 1.0/DIAMETER_RATE);

}

void TreeGen2D::initializeBud(Bud *b){

    float3 dir(b->end.x - b->start.x, b->end.y - b->start.y, b->end.z - b->start.z);
    dir.normalize();
    b->direction = dir;
    float x = b->direction.x;
    float y = b->direction.y;
    float t = (rand() % 100) < 50 ? AUX_ANGLE : -AUX_ANGLE;
    b->auxAngle = t;
    float3 f(x*cos(t) + y * sin(t), x *-sin(t) + y * cos(t), 0);
    b->auxDir =f;
    b->darken = max((double)(rand()%100) /100.0, 0.7);
    //for 3d testing
    b->start.z = 100;
    b->end.z = 100;




}

//interaction for 2D, use color picking, render trees not only to screen but also to a framebuffer
//render to color of an incrementing integer, int % (255*255) = b, int /(255*255) = r, (int-(r*255*255))/255 = g
//then to index back in to find the right branch or tree just do r*g*b
//two fb's? one for branches one for trees, trees can just be in shades, max 255 trees
